package com.authorityManagement.service.impl;

import com.authorityManagement.entity.LoginUser;
import com.authorityManagement.entity.Menu;
import com.authorityManagement.entity.User;
import com.authorityManagement.exception.CustomerExceptionHandler;
import com.authorityManagement.mapper.UserMapper;
import com.authorityManagement.service.UserService;
import com.authorityManagement.util.jwtUtil.JwtUtil;
import com.authorityManagement.vo.TokenVo;
import com.authorityManagement.vo.UserVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
      @Autowired
      private UserMapper userMapper;
      
      @Autowired
      private AuthenticationManager authenticationManager;
      
      @Autowired
      private RedisTemplate redisTemplate;
      
      
      @Override
      public Map<String,Object> login(User user) {
            Map<String, Object> datas = new HashMap<>();
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
            Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
            if (authenticate == null) {
                  throw new CustomerExceptionHandler("账号或密码错误，请重新登录");
            }
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
      
            String token = JwtUtil.createJWT(loginUser.user.getId().toString(), loginUser.getUsername(), 7 * 24 * 60 * 60 * 1000L);
            long tokenExpire = JwtUtil.getTokenExpire(token);
            redisTemplate.opsForValue().set("token:" + token, token,60*2, TimeUnit.MINUTES);
            datas.put("token", token);
            datas.put("expire", tokenExpire);
            return datas;
      
      }
      
      @Override
      public TokenVo refreshToken(String token) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
      
            String newToken = null;
            newToken = JwtUtil.createJWT(loginUser.getUser().getId().toString(), loginUser.getUsername(), 7 * 24 * 60 * 60 * 1000L);
            long newTokenExpire = JwtUtil.getTokenExpire(newToken);
            redisTemplate.delete("token:" + token);
            redisTemplate.opsForValue().set("token:"+newToken,newTokenExpire,60*2, TimeUnit.MINUTES);
            TokenVo tokenVo = new TokenVo();
            tokenVo.setToken(newToken);
            tokenVo.setExpired(newTokenExpire);
            return tokenVo;
      }
      
      @Override
      public UserVo queryUserInfo() {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null) {
                  throw new CustomerExceptionHandler("用户信息不存在");
            }
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            List<Menu> menuList = loginUser.getMenuList();
            List<String> authorityList = null;
            if (!CollectionUtils.isEmpty(menuList)) {
                  authorityList = menuList.stream()
                        .filter(Objects::nonNull)
                        .map(Menu::getPerms)
                        .collect(Collectors.toList());
            }
            User user = loginUser.getUser();
            
            UserVo userVo = new UserVo();
            userVo.setId(user.getId());
            userVo.setName(user.getNickName());
            userVo.setAvatar(user.getAvatar());
            userVo.setRoles(authorityList);
            return userVo;
      }
      
      @Override
      public void logout(HttpServletRequest request, HttpServletResponse response) {
            String token = request.getHeader("token");
            if (!StringUtils.hasText(token)) {
                  token = request.getParameter("token");
            }
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null) {
                  SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
                  securityContextLogoutHandler.logout(request,response,authentication);
            }
            redisTemplate.delete("token:" + token);
            return;
      }
}
